package test.android;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.SystemClock;


public class Shaker extends Activity {
	private SensorManager mgr = null;
	private long lastShakeTimestamp = 0;
	private double threshold = 1.0d;
	private long gap = 0;
	private Shaker.Callback cb = null;
	private VolumeController vc;
	private ModeController mc;
	private boolean isShaked;

	public Shaker(Context ctxt, double threshold, long gap, Shaker.Callback cb,
			VolumeController vc, ModeController mc) {
		this.threshold = threshold * threshold;
		this.threshold = this.threshold * SensorManager.GRAVITY_EARTH
				* SensorManager.GRAVITY_EARTH;
		this.gap = gap;
		this.cb = cb;
		this.vc = vc;
		this.mc = mc;
		//this.isShaked = false;
		mgr = (SensorManager) ctxt.getSystemService(Context.SENSOR_SERVICE);
		mgr.registerListener(listener,
				mgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				SensorManager.SENSOR_DELAY_UI);
		mgr.registerListener(listener,
				mgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
				SensorManager.SENSOR_DELAY_UI);
	}

	public void close() {
		mgr.unregisterListener(listener);
	}

	private void isShaking(SensorEvent e, float volume) {
		long now = SystemClock.uptimeMillis();
		if (lastShakeTimestamp == 0) {
			lastShakeTimestamp = now;
			if (cb != null) {
				
				System.out.println("volume "+volume);
				
				cb.shakingStarted(e, volume);
			}
		} else {
			lastShakeTimestamp = now;
		}
	}

	private void isNotShaking() {
		long now = SystemClock.uptimeMillis();
		if (lastShakeTimestamp > 0) {
			if (now - lastShakeTimestamp > gap) {
				lastShakeTimestamp = 0;
				if (cb != null) {
					cb.shakingStopped();
				}
			}
		}
	}

	public interface Callback {
		void shakingStarted(SensorEvent e, float volume);
		void shakingStopped();
	}

	public SensorEventListener listener = new SensorEventListener() {
		public void onSensorChanged(SensorEvent e) {
			if (e.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
				if (isShaked)
					vc.setVolume(e.values[0], e.values[1], e.values[2]);
			}
			if (e.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
					double netForce = e.values[0] * e.values[0];
					netForce += e.values[1] * e.values[1];
					netForce += e.values[2] * e.values[2];
					mc.add(e.values);
					// System.out.println(netForce);
					if (netForce > threshold) {
						float volume;
						float force = (float) (netForce*10);
						if (force > 5000)
							volume = (float) 1.0;
						else
							volume = (float) 0.2;
						isShaked = true;						
						isShaking(e, volume);																		
					} else {
						isShaked = false;
						isNotShaking();
					}
			}
		}

		public void onAccuracyChanged(Sensor sensor, int accuracy) {
			// unused
		}
	};

}
